/*
 * NewNode.h
 *
 *  Created on: Oct 28, 2012
 *      Author: Federico Orquera
 */

#ifndef NEWNODE_H_
#define NEWNODE_H_

#include <iostream>
#include <string>
#include <stdexcept>
#include <list>
#include <memory>
#include "../bplusregistertemplates/BPlusSimpleRegisterList.h"

#define NULL_NODE_ID 0

class NodeExceptions : public std::runtime_error {
public:
	NodeExceptions(const string& message)
        : std::runtime_error(message) { };
};

enum NodeResulMessages {
	NO_CHANGE, UPDATED, OVERFLOW, DELETED, UNDERFLOW
};

template <
	typename keyTemplate,
	typename valueTemplate,
	bool keyComparator(
		const keyTemplate& key1,
		const keyTemplate& key2
	)
>
class NewNode{

public:

	typedef keyTemplate 	Key_t;
	typedef valueTemplate 	Value_t;

	typedef unsigned int NodeOrder;
	typedef unsigned int NodeLevel;
	typedef unsigned int NodeID;

	typedef BPlusSimpleRegisterList<Key_t, Value_t, keyComparator> 		SimpleRegisterList;
	typedef typename SimpleRegisterList::registerType					registerType;
	typedef typename SimpleRegisterList::register_ptr 					register_ptr;
	typedef typename SimpleRegisterList::registerPointerList 			registerPointerList;
	typedef typename SimpleRegisterList::registerPointerListIterator 	registerPointerListIterator;
	typedef typename SimpleRegisterList::registerPointerList_ptr		registerPointerList_ptr;

	struct searchResult {
		register_ptr result; 	// Registro Mayor o igual a lo que se busca
		NodeID 		 nextNode;	// ID de nodo donde buscar el siguiente
		bool 		 valid;		// True si result es valido
		bool 		 endOfList;	// True si es el ultimo de la lista
	};

	NewNode(NodeOrder newOrder, NodeLevel newLevel, NodeID newNodeID){
		initialize(newOrder, newLevel, newNodeID);
	}

	virtual ~NewNode(){}

	const NodeLevel& getLevel() const {
		return l;
	}

	const NodeID& getNodeID() const {
		return n;
	}

	const NodeOrder& getOrder() const {
		return m;
	}

	virtual NodeResulMessages 	LoadRegister  ( const register_ptr& registro ) = 0;
	virtual NodeResulMessages 	InsertRegister( const register_ptr& registro ) = 0;
	virtual NodeResulMessages 	UpdateRegister( const register_ptr& registro ) = 0;
	virtual NodeResulMessages 	DeleteRegister( const Key_t& key ) = 0;
	virtual searchResult		SearchRegister( const Key_t& key ) = 0;
	virtual void MostrarContenido( const string& separator ) = 0;
	virtual void MostrarContenidoReducido( const string& separator ) = 0;

private:

	void initialize(
			const NodeOrder& newOrder,
			const NodeLevel& newLevel,
			const NodeID& newNodeID
	){
		this->setOrder(newOrder);
		this->setLevel(newLevel);
		this->setNodeID(newNodeID);
	}

protected:

	NodeOrder			m;	// Orden del Arbol. Persistir.
	NodeLevel			l;	// Nivel del Nodo. Persistir.
	NodeID				n;	// ID del nodo. Persistir.

	void setLevel(NodeLevel newLevel) {
		this->l = newLevel;
	}

	void setOrder(NodeOrder newOrder) {
		if(newOrder == 0)
	    	throw NodeExceptions("Node order can't be 0.");
		this->m = newOrder;
	}

	void setNodeID(NodeID newNodeID) {
		this->n = newNodeID;
	}

};


#endif /* NEWNODE_H_ */
